package com.zyfdroid.mindnote2;

import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.*;
import android.widget.*;

import com.zyfdroid.mindnote2.utils.AppSettings;
import com.zyfdroid.mindnote2.utils.DocumentManager;
import com.zyfdroid.mindnote2.utils.DocumentEditingPositionManager;
import com.zyfdroid.mindnote2.utils.RunUtils;
import com.zyfdroid.mindnote2.utils.ShareFileProvider;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;

public class EditorActivity extends BaseActivity {

    WebView webView;

    Runnable afterSaveAction = null;

    public class MindNoteJSBridge{
        @JavascriptInterface
        public void onContentChanged(){
            EditorActivity.this.modified = true;
        }

        @JavascriptInterface
        public void onSaveData(String jsonData,int lineNumber){
            RunUtils.runNoStrict(() -> {
                try {
                    content.content = jsonData;
                    DocumentManager.saveDocumentContent(content);
                    DocumentEditingPositionManager.setDocumentPosition(EditorActivity.this,info,lineNumber);
                    modified = false;
                    if ( EditorActivity.this.thisTimeShowMessage) {
                        runOnUiThread(()->Toast.makeText(EditorActivity.this, "保存成功", Toast.LENGTH_SHORT).show());
                    }
                    if(afterSaveAction != null){
                        runOnUiThread(afterSaveAction);
                        afterSaveAction = null;
                    }
                } catch (IOException e) {
                    runOnUiThread(()->Toast.makeText(EditorActivity.this, "保存失败：" + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show());
                    e.printStackTrace();
                }
            });
        }

    }

    private static final String TAG = "EditorActivity";
    public static final int TAB_WIDTH = 3;
    // EditorActivity.java
    private String getEditorHtml(){
        // 使用 StringBuilder 来高效地构建字符串
        StringBuilder htmlBuilder = new StringBuilder();

        // try-with-resources 语句确保 InputStream 和 BufferedReader 在使用后自动关闭
        try (InputStream inputStream = getAssets().open("editor.html");
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {

            String line;
            // 逐行读取文件内容
            while ((line = reader.readLine()) != null) {
                htmlBuilder.append(line).append("\n"); // 保留换行符
            }

        } catch (IOException e) {
            Log.e(TAG, "Error reading editor.html from assets", e);
            // 发生异常时返回空字符串
            return "";
        }

        // 将 StringBuilder 的内容转换为 String
        String html = htmlBuilder.toString();


        return html;
    }

    private void initUI() {
        webView = findViewById(R.id.webMain);
        webView.setBackgroundColor(Color.TRANSPARENT);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setSupportZoom(false);
        webView.getSettings().setDisplayZoomControls(false);
        webView.getSettings().setBuiltInZoomControls(false);
        webView.getSettings().setDomStorageEnabled(true);
        webView.setWebContentsDebuggingEnabled(true);
        webView.addJavascriptInterface(new MindNoteJSBridge(),"MindNoteJSBridge");
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                runOnUiThread(EditorActivity.this::loadData);
            }
        });
        webView.setWebChromeClient(new WebChromeClient(){
            @Override
            public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
                Log.d(TAG, consoleMessage.messageLevel()+":onConsoleMessage("+consoleMessage.sourceId()+":"+consoleMessage.lineNumber()+"): "+consoleMessage.message());
                return super.onConsoleMessage(consoleMessage);
            }
        });
        webView.loadUrl("file:///android_asset/editor.html");

        if(getActionBar() != null){
            getActionBar().setDisplayHomeAsUpEnabled(true);
            getActionBar().setHomeButtonEnabled(true);
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_editor);
        initUI();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_editor, menu);

        menu.findItem(R.id.mnuEditorRenameView).setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {

                ((EditText)item.getActionView()).setText(content.title);
                Log.w("Did the object changed? ", ""+item.getActionView().toString());
                hWnd.post(()->{
                    ((EditText)item.getActionView()).requestFocus();
                    ((EditText)item.getActionView()).setOnFocusChangeListener((v,hasFocus)->{
                        if(!hasFocus){

                            // Trick: when click the back button on ActionBar ,the button will try to collapse the view by removing the
                            //        EditText, which is already removed due to lost focus, causing NullPointerException, so put it off
                            //        a little time to avoid it.
                            hWnd.postDelayed(item::collapseActionView,100);

                        }
                    });
                });

                return true;
            }

            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {

                String newTitle = ((EditText)item.getActionView()).getText().toString();
                if(TextUtils.isEmpty(newTitle.trim())){
                    newTitle = content.title;
                }
                content.title = newTitle;
                setTitle(content.title);
                modified = true;

                return true;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

    // region Editor


    // endregion

    boolean modified = false;
    DocumentManager.DocumentContent content = null;
    DocumentManager.DocumentInfo info = null;

    public static final String EXTRA_TYPE = "type";
    public static final String EXTRA_FILE = "file";
    public static final String EXTRA_TITLE = "title";

    public static void startEdit(Context ctx, DocumentManager.DocumentInfo info) {
        Intent i = new Intent(ctx, EditorActivity.class);
        i.putExtra(EXTRA_FILE, info.fileName);
        i.putExtra(EXTRA_TYPE, info.isDone);
        i.putExtra(EXTRA_TITLE, info.title);
        ctx.startActivity(i);
    }

    boolean loaded = false;


    private void loadData() {
        info = new DocumentManager.DocumentInfo();
        Intent i = getIntent();
        info.fileName = i.getStringExtra(EXTRA_FILE);
        info.title = i.getStringExtra(EXTRA_TITLE);
        info.isDone = i.getBooleanExtra(EXTRA_TYPE, false);

        RunUtils.runNoStrict(() -> {
            try {
                content = DocumentManager.getDocumentContent(info);
                int position = DocumentEditingPositionManager.getDocumentPosition(EditorActivity.this,info);
                runOnUiThread(() -> {
                    String documentBody = content.content;
                    if(TextUtils.isEmpty(documentBody)){
                        documentBody = "[]";
                    }
                    if(!(documentBody.startsWith("[") && documentBody.endsWith("]"))){
                        AlertDialog.Builder ald = new AlertDialog.Builder(EditorActivity.this);
                        ald.setTitle("数据错误");
                        ald.setMessage("数据错误，尝试加载以下格式的笔记，该笔记为无效的笔记数据。\r\n\r\n"+documentBody);
                        String finalDocumentBody = documentBody;
                        ald.setPositiveButton("复制内容",(di, which)->{
                            ((ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE)).setText(finalDocumentBody);
                        });
                        ald.create().show();
                        loaded = true;
                    }

                    String javascript = "requestLoad("+documentBody+", "+position+");";
                    webView.evaluateJavascript(javascript, new ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String value) {
                            loaded = true;
                            setTitle(content.title);
                        }
                    });
                });
            } catch (IOException e) {
                e.printStackTrace();
                runOnUiThread(() -> {
                    Toast.makeText(this, "读取文件出错：" + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                    finish();
                });
            }
        });
    }
    private boolean thisTimeShowMessage = false;
    private void save(boolean showMessage) {
        thisTimeShowMessage = showMessage;
        if (loaded) {
            webView.evaluateJavascript("requestSave()",null);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (modified) {
            save(false);
        }
        webView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        webView.onResume();
    }

    @Override
    public void onBackPressed() {
        if (modified) {
            save(false);
        }
        super.onBackPressed();
    }

    @Override
    public boolean onNavigateUp() {
        if (modified) {
            save(false);
        }
        finish();
        return true;
    }




    public void mnuSaveClick(MenuItem item) {
        save(true);
    }


    public void mnuShareDocumentClick(MenuItem item) {
        afterSaveAction = new Runnable() {
            @Override
            public void run() {
                // 1. 获取已保存的 JSON 内容
                // 假设 `content.content` 存储的是 getEditorContent() 返回的 JSON 数组字符串
                String jsonContent = content.content;

                // 2. 准备构建 HTML
                StringBuilder bodyHtmlBuilder = new StringBuilder();

                try {
                    // 3. 解析 JSON 数据
                    JSONArray notesArray = new JSONArray(jsonContent);

                    // 4. 遍历数组，为每一行生成一个 <div>
                    for (int i = 0; i < notesArray.length(); i++) {
                        JSONObject noteItem = notesArray.getJSONObject(i);

                        // 获取内容
                        String contentHtml = noteItem.getString("content");

                        // 获取并处理样式类
                        StringBuilder classAttribute = new StringBuilder();
                        JSONArray classesArray = noteItem.optJSONArray("classes"); // 使用 opt 避免空指针
                        if (classesArray != null && classesArray.length() > 0) {
                            classAttribute.append(" class=\"");
                            for (int j = 0; j < classesArray.length(); j++) {
                                if (j > 0) {
                                    classAttribute.append(" ");
                                }
                                classAttribute.append(classesArray.getString(j));
                            }
                            classAttribute.append("\"");
                        }

                        // 构建完整的 div 标签并追加
                        bodyHtmlBuilder.append("<div")
                                .append(classAttribute)
                                .append(">")
                                .append(contentHtml)
                                .append("</div>\n");
                    }

                    // 5. 将生成的 body 内容包装成一个完整的 HTML 文档
                    String fullHtmlDocument = createFullHtmlDocument(bodyHtmlBuilder.toString(),content.title);

                    shareHtmlFile(fullHtmlDocument,content.title);

                } catch (JSONException e) {
                    e.printStackTrace();
                    // 如果解析失败，给用户一个提示
                    Toast.makeText(getApplicationContext(), "Error: Could not prepare document for sharing.", Toast.LENGTH_SHORT).show();
                }
            }
        };
        save(false);
    }

    /**
     * 将 HTML 内容保存到缓存目录的随机文件夹中，并启动分享。
     *
     * @param fullHtmlDocument 要保存的完整 HTML 字符串。
     * @param title            用作文件名的标题。
     */
    private void shareHtmlFile(String fullHtmlDocument, String title) {
        // 1. 创建一个在缓存目录下的随机文件夹
        File cacheDir = new File(getCacheDir(),"share");
        File sharedFolder = new File(cacheDir, UUID.randomUUID().toString());
        if (!sharedFolder.mkdirs()) {
            Log.e(TAG, "Failed to create shared directory");
            Toast.makeText(this, "无法创建临时文件夹", Toast.LENGTH_SHORT).show();
            return;
        }

        // 2. 在该文件夹中创建 HTML 文件
        // 注意：对文件名进行清理，移除非法字符
        String sanitizedTitle = sanitizeFileName(title);
        if (!sanitizedTitle.toLowerCase().endsWith(".htm")) {
            sanitizedTitle += ".htm";
        }
        File htmlFile = new File(sharedFolder, sanitizedTitle);

        // 3. 将 HTML 字符串写入文件
        try (FileOutputStream fos = new FileOutputStream(htmlFile);
             OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
            osw.write(fullHtmlDocument);
            osw.flush();
        } catch (IOException e) {
            Log.e(TAG, "Failed to write HTML to file", e);
            Toast.makeText(this, "无法保存文件", Toast.LENGTH_SHORT).show();
            return;
        }

        // 4. 获取文件的 Uri 并启动分享 Intent
        Uri fileUri = ShareFileProvider.getUriForFile(this, getPackageName(), htmlFile);

        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
        // 使用 "text/html" 更准确，但很多应用也接受 "text/plain"
        shareIntent.setDataAndType(fileUri, "text/html");
        shareIntent.setClipData(ClipData.newRawUri("", fileUri));
        shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        // 启动系统分享选择器
        startActivity(Intent.createChooser(shareIntent, "发送笔记文件"));
    }

    /**
     * 清理文件名，移除或替换不适用于文件系统的字符。
     */
    private String sanitizeFileName(String name) {
        if (name == null || name.isEmpty()) {
            return "untitled";
        }
        // 替换常见的非法字符
        return name.replaceAll("[\\\\/:*?\"<>|]", "_");
    }

    private String createFullHtmlDocument(String string, String title) {
        // 使用 StringBuilder 来高效地构建字符串
        StringBuilder htmlBuilder = new StringBuilder();

        // try-with-resources 语句确保 InputStream 和 BufferedReader 在使用后自动关闭
        try (InputStream inputStream = getAssets().open("html-export-template.html");
             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {

            String line;
            // 逐行读取文件内容
            while ((line = reader.readLine()) != null) {
                htmlBuilder.append(line).append("\n"); // 保留换行符
            }

        } catch (IOException e) {
            Log.e(TAG, "Error reading editor.html from assets", e);
            // 发生异常时返回空字符串
            return "";
        }

        // 将 StringBuilder 的内容转换为 String
        String html = htmlBuilder.toString();

        // 替换占位符
        html = html.replace("{TITLE}", title);
        html = html.replace("{CONTENT}", string);

        return html;
    }

    Runnable waitForExit = new Runnable() {
        @Override
        public void run() {
            if(modified){
                hWnd.postDelayed(this,100);
                Log.w(TAG, "waitForExit: Not saved ,waiting...");
            }
            else{
                Log.w(TAG, "waitForExit: Saved ,Destroying...");
                webView.destroy();
            }
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        hWnd.postDelayed(waitForExit,10);
    }
}